<!-- 
    这个组件是公共组件，点击发送按钮调用的是父组件的发送事件, 发送文件也是
    父组件要定义的方法：
        @sendContent （发送 input 中用户输入的内容，父组件函数要准备形参接收）
        @sendFile （发送用户选中的文件，父组件函数要准备形参接收）
-->
<template>
    <div class="chat-input">
        <div class="container">
            <!-- 焦点设置有问题，每次退出页面再进来，点击显示表情包菜单焦点都是从0开始，而不退出页面就不会 -->
            <div autofocus class="messageInput" contenteditable="true" ref="messageInput" 
                @paste="handlePaste"  
                @copy="handleCopy" 
                @blur="getCaretPosition" 
                @keyup="getCaretPosition" 
            />
            <van-icon ref="icon" @click="clickShowEmoji" size="2.1rem" color="#313132" name="smile-o" />

            <div>
                <van-uploader v-if="!isContent && showUploader" :after-read="afterRead">
                    <van-icon size="2.1rem" name="add-o" />
                </van-uploader>
                <van-button size="small" type="primary" v-else @click="onBut">发送</van-button>
            </div>
        </div>
        
        <Emoji ref="emoji" v-show="hidePicker" @selectEmoji="selectEmoji" />
    </div>
</template>

<script>
    import  Emoji  from "@/components/common/Emoji.vue";
    import { transformImgString } from "@/utils/common";

    export default {
        props: {
            showUploader: {                 // isContent && showUploader 控制是否显示上传文件按钮
                type: Boolean,
                default: false 
            }
        },
        data() {
            return {
                sms: "",                    // 信息内容
                isContent: false,           // 是否有内容
                hidePicker: false,          // 控制表情包菜单显示
                lastEditRange: null,        // 光标位置
            };
        },
        watch: {
            $route(to, from) {              // 退出当前页面隐藏表情包菜单
                this.hidePicker = false;
            },
        },
        components: {
            Emoji
        },
        methods: {
            getCaretPosition() {
                let selection = getSelection()
                this.lastEditRange = selection.getRangeAt(0)
            },
            afterRead(file) {       // 当使用上传文件按钮的时候, 将文件传递给父组件，让父组件发送
                this.$emit("sendFile", file);
            },  
            onBut() {               // 发送消息
                const messageInput = this.$refs.messageInput;   
                // 获取输入框的内容
                this.$emit("sendContent", transformImgString(messageInput.innerHTML));
                // 将内容传递给父组件之后清空输入框
                messageInput.innerHTML = ''
            },
            handlePaste(e) {        // 阻止复制的文本到输入框内，会自带css样式：
                e.preventDefault()
                let text
                let clp = (e.originalEvent || e).clipboardData

                if (clp === undefined || clp === null) {
                    text = window.clipboardData.getData("text") || ""
                    if (text !== "") {
                        if (window.getSelection) {
                            var newNode = document.createElement("span")
                            newNode.innerHTML = text;
                            window.getSelection().getRangeAt(0).insertNode(newNode)
                        } else {
                            document.selection.createRange().pasteHTML(text)
                        }
                    }
                } else {
                    text = clp.getData('text/plain') || ""
                    if (text !== "") {
                        document.execCommand('insertText', false, text)
                    }
                }
            },
            handleCopy(event) {    // 复制输入框的内容
                const messageInput = this.$refs.messageInput;
                const htmlContent = messageInput.innerHTML;
                navigator.clipboard.writeText(transformImgString(htmlContent))
            },
            selectEmoji(index) {   // 选择表情包
                let emojiImg = `<img src="./gif/${index}.gif" width="25" height="25" style="vertical-align: middle;">`;
                document.execCommand('insertHTML', false, emojiImg)
            },
            clickShowEmoji() {     // 点击显示表情包菜单
                let selection = getSelection()
                let range = document.createRange();
                let messageInput = this.$refs.messageInput;

                if (!this.isContent) {   // 如果输入框为空设置初始焦点方便插入表情包
                    messageInput.focus();
                    this.lastEditRange = selection.getRangeAt(0)  
                }

                range.selectNodeContents(messageInput);
                range.collapse(false);
                
                selection = getSelection();
                selection.removeAllRanges();
                selection.addRange(this.lastEditRange);
                messageInput.focus();

                this.hidePicker = !this.hidePicker;
                this.$emit("clickIcon");
            },
            clickHandler(event) {
                const icon = this.$refs.icon;
                const emoji = this.$refs.emoji;

                if (!(icon == event.target) && !(emoji.$el.contains(event.target))) {
                    this.hidePicker = false;
                }
            },
        },
        mounted() {
            const targetNode = this.$refs.messageInput;
            const config = { childList: true, subtree: true, characterData: true };

            // 检测输入框是否有内容
            const callback = (mutationsList) => {
            for (let mutation of mutationsList) 
                if (mutation.type === 'childList' || mutation.type === 'characterData') 
                    if (String(targetNode.innerHTML) === '' || String(targetNode.innerHTML) === '<br>') 
                        this.isContent = false;
                    else 
                        this.isContent = true;
            };

            const observer = new MutationObserver(callback);
            observer.observe(targetNode, config);

            // 添加全局点击事件监听器
            document.addEventListener('click', this.clickHandler);
        },
        beforeDestroy() {
            document.removeEventListener('click', this.clickHandler);
        },
    };
</script>

<style lang="less" scoped>
    .chat-input {
        width: 100%;
        .container {
            width: 100%;
            background: #fff;
            padding: .4375rem .3125rem;
            box-sizing: border-box;
            display: flex;
            justify-content: space-around;
            align-items: flex-end;
            .messageInput {
                max-height: 100px;
                width: 70%;
                overflow: auto;
                background: rgba(243, 244, 246, 1); 
                border-radius: 5px;
                line-height: 2.1rem;
                padding: 0 10px;
                border: 0;
                outline: none;
            }
        }
    }
</style>
